package com.ruoyi.system.service.impl;

import cn.hutool.db.PageResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.HomeBannerDTO;
import com.ruoyi.system.dto.HomeBannerQueryDTO;
import com.ruoyi.system.dto.convert.HomeBannerConverter;
import com.ruoyi.system.entity.HomeBannerDO;
import com.ruoyi.system.mapper.HomeBannerMapper;
import com.ruoyi.system.service.HomeBannerService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 首页Banner轮播图配置服务实现
 */
@Service
@RequiredArgsConstructor
public class HomeBannerServiceImpl extends ServiceImpl<HomeBannerMapper, HomeBannerDO> implements HomeBannerService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addBanner(HomeBannerDTO bannerDTO) {
        // 获取当前登录用户ID
        Long userId = SecurityUtils.getUserId();

        // 转换DTO为DO
        HomeBannerDO bannerDO = HomeBannerConverter.INSTANCE.dtoToDo(bannerDTO);

        // 设置创建人
        bannerDO.setCreatedBy(userId);

        // 如果是新增，计算排序值（取当前最大排序值+1）
        int maxSort = baseMapper.selectObjs(new LambdaQueryWrapper<HomeBannerDO>()
                        .eq(HomeBannerDO::getDeleted, 0)
                        .select(HomeBannerDO::getSort)
                        .orderByDesc(HomeBannerDO::getSort)
                        .last("LIMIT 1"))
                .stream()
                .mapToInt(obj -> obj != null ? (Integer) obj : 0)
                .findFirst()
                .orElse(0);
        bannerDO.setSort(maxSort + 1);


        // 保存数据
        baseMapper.insert(bannerDO);
        return bannerDO.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBanner(HomeBannerDTO bannerDTO) {
        // 验证Banner是否存在
        HomeBannerDO existingBanner = baseMapper.selectById(bannerDTO.getId());
        if (existingBanner == null) {
            throw new ServiceException("Banner不存在");
        }

        // 获取当前登录用户ID
        Long userId = SecurityUtils.getUserId();

        // 转换DTO为DO
        HomeBannerDO bannerDO = HomeBannerConverter.INSTANCE.dtoToDo(bannerDTO);

        // 设置更新人
        bannerDO.setUpdatedBy(userId);
        // 更新数据
        baseMapper.updateById(bannerDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBanner(Long id) {
        // 验证Banner是否存在
        HomeBannerDO bannerDO = baseMapper.selectById(id);
        if (bannerDO == null) {
            throw new ServiceException("Banner不存在");
        }

        // 检查是否为上线状态
        if (bannerDO.getStatus() == 1) {
            throw new ServiceException("该Banner当前为已上线状态，请先取消上线后再删除");
        }

        // 删除Banner（逻辑删除）
        baseMapper.deleteById(id);

        // 重新排序剩余Banner
        resetBannerSortAfterDelete(bannerDO.getSort());
    }

    @Override
    public HomeBannerDTO getBannerById(Long id) {
        HomeBannerDO bannerDO = baseMapper.selectById(id);
        if (bannerDO == null) {
            throw new ServiceException("Banner不存在");
        }
        return HomeBannerConverter.INSTANCE.doToDto(bannerDO);
    }

    @Override
    public IPage<HomeBannerDO> queryBannerPage(HomeBannerQueryDTO queryDTO) {
        // 构建查询条件
        LambdaQueryWrapper<HomeBannerDO> queryWrapper = new LambdaQueryWrapper<HomeBannerDO>()
                .eq(queryDTO.getStatus() != null, HomeBannerDO::getStatus, queryDTO.getStatus())
                .like(StringUtils.isNotBlank(queryDTO.getTitle()), HomeBannerDO::getTitle, queryDTO.getTitle())
                .eq(HomeBannerDO::getDeleted, 0)
                .orderByAsc(HomeBannerDO::getSort);

        // 分页查询
        Page<HomeBannerDO> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        return baseMapper.selectPage(page, queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBannerSort(Long id, Integer newSort) {
        // 验证Banner是否存在
        HomeBannerDO bannerDO = baseMapper.selectById(id);
        if (bannerDO == null) {
            throw new ServiceException("Banner不存在");
        }

        Integer oldSort = bannerDO.getSort();

        // 如果新旧排序值相同，无需处理
        if (oldSort.equals(newSort)) {
            return;
        }

        // 更新排序
        if (newSort > oldSort) {
            // 新排序值大于旧排序值，需要将中间的Banner排序值减1
            baseMapper.update(null,
                    new LambdaUpdateWrapper<HomeBannerDO>()
                            .setSql("sort = sort - 1")  // 使用SQL表达式进行算术运算
                            .gt(HomeBannerDO::getSort, oldSort)
                            .le(HomeBannerDO::getSort, newSort)
                            .eq(HomeBannerDO::getDeleted, 0));
        } else {
            // 新排序值小于旧排序值，需要将中间的Banner排序值加1
            baseMapper.update(null,
                    new LambdaUpdateWrapper<HomeBannerDO>()
                            .setSql("sort = sort - 1")  // 使用SQL表达式进行算术运算
                            .lt(HomeBannerDO::getSort, oldSort)
                            .ge(HomeBannerDO::getSort, newSort)
                            .eq(HomeBannerDO::getDeleted, 0));
        }

        // 更新当前Banner的排序值
        bannerDO.setSort(newSort);
        bannerDO.setUpdatedBy(SecurityUtils.getUserId());
        baseMapper.updateById(bannerDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBannerStatus(Long id, Integer status) {
        // 验证Banner是否存在
        HomeBannerDO bannerDO = baseMapper.selectById(id);
        if (bannerDO == null) {
            throw new ServiceException("Banner不存在");
        }

        // 更新状态
        bannerDO.setStatus(status);
        bannerDO.setUpdatedBy(SecurityUtils.getUserId());
        baseMapper.updateById(bannerDO);
    }

    /**
     * 删除后重新排序
     * @param deletedSort 被删除Banner的排序值
     */
    private void resetBannerSortAfterDelete(Integer deletedSort) {
        // 将排序值大于被删除Banner的排序值的Banner排序值减1
        baseMapper.update(null,
                new LambdaUpdateWrapper<HomeBannerDO>()
                        .setSql("sort = sort - 1")  // 使用SQL表达式进行算术运算
                        .gt(HomeBannerDO::getSort, deletedSort)
                        .eq(HomeBannerDO::getDeleted, 0));
    }

}
